/*
 * Copyright 2008 by Emeric Vernat
 *
 *     This file is part of MSwing.
 *
 * MSwing is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * MSwing is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with MSwing.  If not, see <http://www.gnu.org/licenses/>.
 */
package mswing.print;

import java.io.File;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.swing.filechooser.FileFilter;

/**
 * A convenience implementation of FileFilter that filters out all files except for those type
 * extensions that it knows about.
 *
 * Extensions are of the type ".foo", which is typically found on Windows and Unix boxes, but not on
 * Macinthosh. Case is ignored.
 *
 * Example - create a new filter that filters out all files but gif and jpg image files:
 *
 * JFileChooser chooser = new JFileChooser(); MExtensionFileFilter filter = new
 * MExtensionFileFilter( new String{"gif", "jpg"}, "JPEG & GIF Images")
 * chooser.addChoosableFileFilter(filter); chooser.showOpenDialog(this);
 *
 * @author Jeff Dinkins, Sun
 */
class MExtensionFileFilter extends FileFilter {
	private Map filters;
	private String description;
	private String fullDescription;
	private boolean useExtensionsInDescription = true;

	/**
	 * Creates a file filter. If no filters are added, then all files are accepted.
	 *
	 * @see #addExtension
	 */
	MExtensionFileFilter() {
		super();
		this.filters = new HashMap(0);
	}

	/**
	 * Creates a file filter from the given string array and description. Example: new
	 * MExtensionFileFilter(String {"gif", "jpg"}, "Gif and JPG Images");
	 *
	 * Note that the "." before the extension is not needed and will be ignored.
	 *
	 * @param filters String[]
	 * @param description String, may be null
	 * @see #addExtension
	 */
	MExtensionFileFilter(String[] filters, String description) {
		this();
		for (int i = 0; i < filters.length; i++) {
			// add filters one by one
			addExtension(filters[i]);
		}
		if (description != null) {
			setDescription(description);
		}
	}

	/**
	 * Creates a file filter that accepts files with the given extension. Example: new
	 * MExtensionFileFilter("jpg");
	 *
	 * @param extension String
	 * @see #addExtension
	 */
	MExtensionFileFilter(String extension) {
		this(extension, null);
	}

	/**
	 * Creates a file filter that accepts the given file type. Example: new
	 * MExtensionFileFilter("jpg", "JPEG Image Images");
	 *
	 * Note that the "." before the extension is not needed. If provided, it will be ignored.
	 *
	 * @param extension String
	 * @param description String
	 * @see #addExtension
	 */
	MExtensionFileFilter(String extension, String description) {
		this();
		if (extension != null) {
			addExtension(extension);
		}
		if (description != null) {
			setDescription(description);
		}
	}

	/**
	 * Return true if this file should be shown in the directory pane, false if it shouldn't.
	 *
	 * Files that begin with "." are ignored.
	 *
	 * @return boolean
	 * @param file java.io.File
	 * @see #getExtension
	 * @see javax.swing.filechooser.FileFilter#accept
	 */
	public boolean accept(File file) {
		if (file != null) {
			if (file.isDirectory()) {
				return true;
			}

			final String extension = getExtension(file);
			if (extension != null && filters.containsKey(extension)) {
				return true;
			}
		}
		return false;
	}

	/**
	 * Adds a filetype "dot" extension to filter against.
	 *
	 * For example: the following code will create a filter that filters out all files except those
	 * that end in ".jpg" and ".tif":
	 *
	 * MExtensionFileFilter filter = new MExtensionFileFilter(); filter.addExtension("jpg");
	 * filter.addExtension("tif");
	 *
	 * Note that the "." before the extension is not needed and will be ignored.
	 *
	 * @param extension String
	 */
	public void addExtension(String extension) {
		if (filters == null) {
			filters = new HashMap(1);
		}

		filters.put(extension.toLowerCase(), this);
		fullDescription = null;
	}

	/**
	 * Returns the human readable description of this filter. For example:
	 * "JPEG and GIF Image Files (*.jpg, *.gif)"
	 *
	 * @return String
	 * @see #setDescription
	 * @see #setExtensionListInDescription
	 * @see #isExtensionListInDescription
	 * @see javax.swing.filechooser.FileFilter#getDescription
	 */
	public String getDescription() {
		if (fullDescription == null) {
			String temp;
			if (description == null || isExtensionListInDescription()) {
				final StringBuffer sb = new StringBuffer();
				sb.append(description == null ? "(" : description + " (");
				// build the description from the extension list
				final Iterator it = filters.keySet().iterator();
				sb.append("*.");
				sb.append((String) it.next());
				while (it.hasNext()) {
					sb.append(", *.");
					sb.append((String) it.next());
				}
				sb.append(')');
				temp = sb.toString();
			} else {
				temp = description;
			}

			// Command Query Separation with lazy initialization : set
			// fullDescription only once
			fullDescription = temp;
		}
		return fullDescription;
	}

	/**
	 * Return the extension portion of the file's name.
	 *
	 * @return String
	 * @param file java.io.File
	 */
	public String getExtension(File file) {
		if (file != null) {
			final String fileName = file.getName();
			final int i = fileName.lastIndexOf('.');
			if (i > 0 && i < fileName.length() - 1) {
				return fileName.substring(i + 1).toLowerCase();
			}
		}
		return null;
	}

	/**
	 * Returns whether the extension list (.jpg, .gif, etc) should show up in the human readable
	 * description.
	 *
	 * Only relevent if a description was provided in the constructor or using setDescription();
	 *
	 * @return boolean
	 * @see #getDescription
	 * @see #setDescription
	 * @see #setExtensionListInDescription
	 */
	public boolean isExtensionListInDescription() {
		return useExtensionsInDescription;
	}

	/**
	 * Sets the human readable description of this filter. For example:
	 * filter.setDescription("Gif and JPG Images");
	 *
	 * @param description String
	 * @see #getDescription
	 * @see #setExtensionListInDescription
	 * @see #isExtensionListInDescription
	 */
	public void setDescription(String description) {
		this.description = description;
		fullDescription = null;
	}

	/**
	 * Determines whether the extension list (.jpg, .gif, etc) should show up in the human readable
	 * description.
	 *
	 * Only relevent if a description was provided in the constructor or using setDescription();
	 *
	 * @param bool boolean
	 * @see #getDescription
	 * @see #setDescription
	 * @see #isExtensionListInDescription
	 */
	public void setExtensionListInDescription(boolean bool) {
		useExtensionsInDescription = bool;
		fullDescription = null;
	}
}
